/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ComprasPanel.java
 *
 * Created on 25/11/2011, 18:03:18
 */
package org.tri.gui;

import furbelow.SpinningDial;
import java.awt.CardLayout;
import java.awt.event.ItemEvent;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
import javax.swing.text.DefaultFormatterFactory;
import org.tri.entity.AbstractAnimal;
import org.tri.entity.Compra;
import org.tri.entity.Establecimiento;
import org.tri.gui.worker.CompraPersistenceWorker;
import org.tri.gui.worker.PersistenceListener;
import org.tri.gui.worker.PersistenceWorker;
import org.tri.gui.worker.exceptions.AnimalDuplicadoException;
import org.tri.persistence.search.BusquedaCompra;
import org.tri.persistence.search.BusquedaCompraHistorica;

/**
 *
 * @author giaco
 */
public class ComprasPanel extends javax.swing.JPanel {

    /** Modelo para la lista de caravanas. */
    private DefaultListModel caravanasListModel;
    /** Ultima caravana del establecimiento. */
    private String ultimaCaravana;
    /** Icono de loading para las transacciones. */
    private Icon loadingIcon;
    /** Frame donde este panel se encuentra. */
    private MainFrame frame;
    /** Grupo de radio buttons utilizado en el panel. */
    private ButtonGroup rBGroup;
    /** Text field para la ultima caravana. */
    private Object ultimaCaravanaComponents[];
    /** Layout del panel de input de caravanas. */
    private CardLayout layoutCaravanasInput;

    /** Creates new form ComprasPanel */
    public ComprasPanel() {
        //creamos el modelo para la lista de caravanas
        caravanasListModel = new DefaultListModel();

        //inicializamos el icono de loading
        loadingIcon = new SpinningDial( 20, 20, 10 );

        //creamos el group para los botones rb
        rBGroup = new ButtonGroup();
        
        //inicializamos los componentes del dialog de ultima caravana
        ultimaCaravanaComponents = new Object[2];
        
        ultimaCaravanaComponents[0] = "La caravana inicial utilizada para\n"
        + "generar nuevas caravanas no fué inicializada.\nPor favor ingrese una "
        + "a continuación.";
                                
        initComponents();
        
        //obtenemos el layout del panel de input de caravanas
        layoutCaravanasInput = (CardLayout)JPInputCaravanas.getLayout();
        
    }

    public ComprasPanel( MainFrame frame ) {
        this();

        this.frame = frame;

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings ( "unchecked" )
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPCentral = new javax.swing.JPanel();
        jPDatos = new javax.swing.JPanel();
        jLfecha = new javax.swing.JLabel();
        jXDPFecha = new org.jdesktop.swingx.JXDatePicker( new Date() );
        jLTipoFactura = new javax.swing.JLabel();
        jTFTipoFactura = new javax.swing.JTextField();
        jLNumeroFactura = new javax.swing.JLabel();
        jFTFNumeroFactura = new javax.swing.JFormattedTextField();
        filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        jLTRI = new javax.swing.JLabel();
        jRBsi = new javax.swing.JRadioButton();
        jRBno = new javax.swing.JRadioButton();
        jLDTA = new javax.swing.JLabel();
        jFTFDta = new javax.swing.JFormattedTextField();
        jLRenspa = new javax.swing.JLabel();
        jFTFRenspa = new javax.swing.JFormattedTextField();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 0), new java.awt.Dimension(32767, 0));
        filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 15), new java.awt.Dimension(0, 15), new java.awt.Dimension(32767, 15));
        jPCaravanas = new javax.swing.JPanel();
        jSPCaravanas = new javax.swing.JScrollPane();
        jLcaravanas = new javax.swing.JList(caravanasListModel);
        jBQuitar = new javax.swing.JButton();
        jBLimpiar = new javax.swing.JButton();
        jBguardar = new javax.swing.JButton();
        jLGuardarWaitIcon = new javax.swing.JLabel();
        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 0), new java.awt.Dimension(32767, 0));
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 32767));
        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        JPInputCaravanas = new javax.swing.JPanel();
        jPCaravanasPropias = new javax.swing.JPanel();
        jLCantidadPropias = new javax.swing.JLabel();
        jFTFCantidadPropias = new javax.swing.JFormattedTextField();
        jPCaravanasCompradas = new javax.swing.JPanel();
        jLTituloIngresoManual = new javax.swing.JLabel();
        jLCaravana = new javax.swing.JLabel();
        jFTFCaravana = new javax.swing.JFormattedTextField();
        jSSeparatorInputCaravana = new javax.swing.JSeparator();
        jLTituloIngresoLote = new javax.swing.JLabel();
        jLCaravanaInicial = new javax.swing.JLabel();
        jFTFCaravanaInicial = new javax.swing.JFormattedTextField();
        jLCantidadCompradas = new javax.swing.JLabel();
        jFTFCantidadCompradas = new javax.swing.JFormattedTextField();
        jBagregarLote = new javax.swing.JButton();
        filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));

        setLayout(new java.awt.BorderLayout());

        jPCentral.setLayout(new java.awt.GridBagLayout());

        jPDatos.setBorder(javax.swing.BorderFactory.createTitledBorder("Datos"));
        jPDatos.setLayout(new java.awt.GridBagLayout());

        jLfecha.setText("Fecha:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPDatos.add(jLfecha, gridBagConstraints);

        jXDPFecha.setFormats( "dd-MM-yyyy" );
        jXDPFecha.setNextFocusableComponent(jRBsi);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jXDPFecha, gridBagConstraints);

        jLTipoFactura.setText("Tipo factura:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPDatos.add(jLTipoFactura, gridBagConstraints);

        jTFTipoFactura.setColumns(8);
        jTFTipoFactura.setMinimumSize(new java.awt.Dimension(98, 25));
        jTFTipoFactura.setNextFocusableComponent(jFTFNumeroFactura);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jTFTipoFactura, gridBagConstraints);

        jLNumeroFactura.setText("Número Factura:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPDatos.add(jLNumeroFactura, gridBagConstraints);

        jFTFNumeroFactura.setColumns(8);
        jFTFNumeroFactura.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        jFTFNumeroFactura.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFNumeroFactura.setNextFocusableComponent(jFTFDta);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jFTFNumeroFactura, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPDatos.add(filler8, gridBagConstraints);

        jLTRI.setText("TRI:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPDatos.add(jLTRI, gridBagConstraints);

        rBGroup.add(jRBsi);
        jRBsi.setText("Si");
        jRBsi.setNextFocusableComponent(jRBno);
        jRBsi.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRBsiItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jRBsi, gridBagConstraints);

        rBGroup.add(jRBno);
        jRBno.setText("No");
        jRBno.setNextFocusableComponent(jTFTipoFactura);
        jRBno.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRBnoItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jRBno, gridBagConstraints);

        jLDTA.setText("DTA:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPDatos.add(jLDTA, gridBagConstraints);

        jFTFDta.setColumns(8);
        jFTFDta.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        jFTFDta.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFDta.setNextFocusableComponent(jFTFRenspa);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jFTFDta, gridBagConstraints);

        jLRenspa.setText("Renspa:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPDatos.add(jLRenspa, gridBagConstraints);

        jFTFRenspa.setColumns(8);
        try {
            jFTFRenspa.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("##-###-#-#####-##")));
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
        }
        jFTFRenspa.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFRenspa.setNextFocusableComponent(jFTFCantidadPropias);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPDatos.add(jFTFRenspa, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        jPDatos.add(filler1, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPDatos.add(filler5, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 8;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPDatos.add(filler6, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        jPCentral.add(jPDatos, gridBagConstraints);

        jPCaravanas.setBorder(javax.swing.BorderFactory.createTitledBorder("Caravanas"));
        jPCaravanas.setLayout(new java.awt.GridBagLayout());

        jSPCaravanas.setPreferredSize(new java.awt.Dimension(150, 130));
        jSPCaravanas.setViewportView(jLcaravanas);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weighty = 1.0;
        jPCaravanas.add(jSPCaravanas, gridBagConstraints);

        jBQuitar.setText("Quitar");
        jBQuitar.setNextFocusableComponent(jBLimpiar);
        jBQuitar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBQuitarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 2;
        jPCaravanas.add(jBQuitar, gridBagConstraints);

        jBLimpiar.setText("Limpiar");
        jBLimpiar.setNextFocusableComponent(jBguardar);
        jBLimpiar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBLimpiarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 2;
        jPCaravanas.add(jBLimpiar, gridBagConstraints);

        jBguardar.setText("Guardar");
        jBguardar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBguardarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        jPCaravanas.add(jBguardar, gridBagConstraints);

        jLGuardarWaitIcon.setMaximumSize(new java.awt.Dimension(25, 25));
        jLGuardarWaitIcon.setMinimumSize(new java.awt.Dimension(25, 25));
        jLGuardarWaitIcon.setPreferredSize(new java.awt.Dimension(25, 25));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
        jPCaravanas.add(jLGuardarWaitIcon, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        jPCaravanas.add(filler3, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 8;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weighty = 1.0;
        jPCaravanas.add(filler2, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPCaravanas.add(filler4, gridBagConstraints);

        JPInputCaravanas.setLayout(new java.awt.CardLayout());

        jPCaravanasPropias.setBorder(null);
        jPCaravanasPropias.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        jLCantidadPropias.setText("Cantidad:");
        jPCaravanasPropias.add(jLCantidadPropias);

        jFTFCantidadPropias.setColumns(8);
        jFTFCantidadPropias.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        jFTFCantidadPropias.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFCantidadPropias.setNextFocusableComponent(jFTFCaravana);
        jFTFCantidadPropias.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jFTFCantidadPropiasActionPerformed(evt);
            }
        });
        jPCaravanasPropias.add(jFTFCantidadPropias);

        JPInputCaravanas.add(jPCaravanasPropias, "caravanasPropiasCard");

        jPCaravanasCompradas.setBorder(null);
        jPCaravanasCompradas.setLayout(new java.awt.GridBagLayout());

        jLTituloIngresoManual.setText("Ingreso Manual");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
        jPCaravanasCompradas.add(jLTituloIngresoManual, gridBagConstraints);

        jLCaravana.setText("Caravana:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPCaravanasCompradas.add(jLCaravana, gridBagConstraints);

        jFTFCaravana.setColumns(8);
        try {
            jFTFCaravana.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("UU###U###")));
        } catch ( Exception ex ) {}
        jFTFCaravana.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFCaravana.setNextFocusableComponent(jFTFCaravanaInicial);
        jFTFCaravana.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jFTFCaravanaActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPCaravanasCompradas.add(jFTFCaravana, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 0);
        jPCaravanasCompradas.add(jSSeparatorInputCaravana, gridBagConstraints);

        jLTituloIngresoLote.setText("Ingreso por Lote");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
        jPCaravanasCompradas.add(jLTituloIngresoLote, gridBagConstraints);

        jLCaravanaInicial.setText("Caravana inicial:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPCaravanasCompradas.add(jLCaravanaInicial, gridBagConstraints);

        jFTFCaravanaInicial.setColumns(8);
        try {
            jFTFCaravanaInicial.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("UU###U###")));
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
        }
        jFTFCaravanaInicial.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFCaravanaInicial.setNextFocusableComponent(jFTFCantidadCompradas);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPCaravanasCompradas.add(jFTFCaravanaInicial, gridBagConstraints);

        jLCantidadCompradas.setText("Cantidad:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPCaravanasCompradas.add(jLCantidadCompradas, gridBagConstraints);

        jFTFCantidadCompradas.setColumns(5);
        jFTFCantidadCompradas.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        jFTFCantidadCompradas.setMinimumSize(new java.awt.Dimension(65, 25));
        jFTFCantidadCompradas.setNextFocusableComponent(jBagregarLote);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPCaravanasCompradas.add(jFTFCantidadCompradas, gridBagConstraints);

        jBagregarLote.setText("Agregar Lote");
        jBagregarLote.setNextFocusableComponent(jBQuitar);
        jBagregarLote.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBagregarLoteActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
        jPCaravanasCompradas.add(jBagregarLote, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 7;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPCaravanasCompradas.add(filler7, gridBagConstraints);

        JPInputCaravanas.add(jPCaravanasCompradas, "caravanasCompradasCard");

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPCaravanas.add(JPInputCaravanas, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPCentral.add(jPCaravanas, gridBagConstraints);

        add(jPCentral, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    private void jBguardarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBguardarActionPerformed
        //builder para almacenar los errores
        StringBuilder error = new StringBuilder();

        //obtenemos el establecimiento con el que estamos trabajando
        Establecimiento establecimiento = frame.getEstablecimiento();
        
        // creo una nueva compra y seteo sus atributos
        Compra compra = establecimiento.crearCompra();

        compra.setFecha( jXDPFecha.getDate() );

        //me fijo si la compra fue con tri o sin el
        if ( rBGroup.isSelected( jRBno.getModel() ) ) {
            //controlo que se halla llenado el campo tipoFactura
            if ( !jTFTipoFactura.getText().equals( "" ) )
                compra.setTipoFactura( jTFTipoFactura.getText() );
            else
                error.append( 
                        "- El campo \"Tipo de factura\" no fué completado." );

            //controlo que se halla llenado el campo numeroFactura
            try {
                jFTFNumeroFactura.commitEdit();
                compra.setNroFactura(
                        Math.abs( (Long)jFTFNumeroFactura.getValue() ) );
            } catch ( ParseException pE ) {
                error.append( ( error.length() > 0 ) ? "\n" : "" );
                error.append( 
                        "- El campo \"Número de factura\" no fué completado." );

            }

        } else {
            //controlo que se haya llenado el campo DTA
            try {
                jFTFDta.commitEdit();
                compra.setDtaOrigen( Math.abs( (Long)jFTFDta.getValue() ) );
            } catch ( ParseException pE ) {
                error.append( "- El campo \"DTA\" no fué completado." );

            }

            //controlo que se haya llenado el campo Renspa           
            try {
                jFTFRenspa.commitEdit();
                compra.setRenspaOrigen( 
                        Establecimiento.renspaAsLong( (String)jFTFRenspa.getValue() ) );
            } catch ( ParseException pE ) {
                error.append( ( error.length() > 0 ) ? "\n" : "" );
                error.append( "- El campo \"Renspa\" no fué completado." );

            }

        }

        //transformo la lista de objetos de animales seleccionados
        List<String> animales = new ArrayList<String>();
        for ( Object o : caravanasListModel.toArray() )
            animales.add( (String)o );

        //controlo que se hallan cargado animales
        if ( !animales.isEmpty() )
            compra.agregarAnimales( animales );
        else {
            error.append( ( error.length() > 0 ) ? "\n" : "" );
            error.append( "- No se ingreso ningúna caravana para la compra." );

        }

        if ( error.length() == 0 ) {
            //valido la existencia de la compra en la bd
            if( validarDatos( compra ) ){
                //lanzamos las tareas de gui previas al almacenado
                fireGuardarTriggers( true );

                //realizamos las tareas de almacenado en un thread aparte
                PersistenceWorker worker = new CompraPersistenceWorker(
                        compra, true );
            
                worker.addPersistenceListener( 
                        new CompraPeristenceHandler( establecimiento) );
            
                worker.execute();
                
            } else
                JOptionPane.showMessageDialog(
                    this, "Ya existe una compra con los datos ingresados",
                    "Error", 
                    JOptionPane.WARNING_MESSAGE );

        } else
            JOptionPane.showMessageDialog(
                    this, error.toString(),
                    "No se completaron todos los campos", 
                    JOptionPane.WARNING_MESSAGE );

    }//GEN-LAST:event_jBguardarActionPerformed

    private void jFTFCantidadPropiasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFTFCantidadPropiasActionPerformed
        //obtenemos la ultima caravana si no la tenemos
        if ( ultimaCaravana == null && !pedirUltimaCaravana() ) 
            return;

        //generamos y agregamos las nuevas caravanas
        List<String> caravanas = AbstractAnimal.generarCaravanas(
                ultimaCaravana,
                ( Math.abs(
                 ( (Long)jFTFCantidadPropias.getValue() ).intValue() ) ));

        for ( int i = 0; i <= caravanas.size() - 1; i++ )
            caravanasListModel.addElement( caravanas.get( i ) );

        //asignamos la nueva última caravana
        ultimaCaravana = caravanas.get( caravanas.size() - 1 );

        //limpiamos el text field
        jFTFCantidadPropias.setValue( null );

    }//GEN-LAST:event_jFTFCantidadPropiasActionPerformed

    private void jFTFCaravanaActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jFTFCaravanaActionPerformed
        //agrego la caravana copiada a la lista
        String caravana = (String)jFTFCaravana.getValue();
        
        if ( !comprobarCaravanaPropia( caravana ) && 
             !caravanasListModel.contains( caravana ) )
            caravanasListModel.addElement( caravana );
        else
            jFTFCaravana.requestFocus();

        //seteo el campo a blanco para que pueda cargar nuevamente
        jFTFCaravana.setValue( null );
       
    }//GEN-LAST:event_jFTFCaravanaActionPerformed

    private void jBLimpiarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBLimpiarActionPerformed
        if ( JOptionPane.showConfirmDialog(
                this, "¿Seguro que desea limpiar el formulario?", "Confirmación",
                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
             == JOptionPane.YES_OPTION )
            limpiarPanel();

    }//GEN-LAST:event_jBLimpiarActionPerformed

    private void jBQuitarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBQuitarActionPerformed
        //obtengo los indice de las caravanas seleccionadas
        int indices[] = jLcaravanas.getSelectedIndices();

        //eliminamos las caravanas de la lista
        for ( int i = indices.length - 1; i >= 0; i-- )
            caravanasListModel.remove( indices[i] );
        
    }//GEN-LAST:event_jBQuitarActionPerformed

    private void jRBsiItemStateChanged( java.awt.event.ItemEvent evt ) {//GEN-FIRST:event_jRBsiItemStateChanged
        if ( evt.getStateChange() == ItemEvent.SELECTED ) {
            //habilito los campos dta y renspa
            jFTFDta.setEnabled( true );
            jFTFRenspa.setEnabled( true );
            
            //habilito el boton de quitar
            jBQuitar.setEnabled( true );
            
            //cambiamos a la card correspondiente
            layoutCaravanasInput.last( JPInputCaravanas );
            
        } else {
            //deshabilito los campos dta y renspa
            jFTFDta.setEnabled( false );
            jFTFRenspa.setEnabled( false );

            //limpiamos la lista de caravanas por que ya no sirve
            caravanasListModel.clear();
            
        }
        
    }//GEN-LAST:event_jRBsiItemStateChanged

    private void jRBnoItemStateChanged( java.awt.event.ItemEvent evt ) {//GEN-FIRST:event_jRBnoItemStateChanged
        if ( evt.getStateChange() == ItemEvent.SELECTED ) {
            //habilito los campos tipo y numero de factura
            jTFTipoFactura.setEnabled( true );
            jFTFNumeroFactura.setEnabled( true );
            
            //deshabilito el boton de quitar (no se deberian quitar caravanas)
            jBQuitar.setEnabled( false );
            
            //cambiamos a la card correspondiente
            layoutCaravanasInput.first( JPInputCaravanas );

        } else {
            //habilito los campos tipo y numero de factura
            jTFTipoFactura.setEnabled( false );
            jFTFNumeroFactura.setEnabled( false );
            
            //limpiamos la lista de caravanas por que ya no sirve
            caravanasListModel.clear();
            
            //y reseteamos la ultima caravana
            ultimaCaravana = frame.getEstablecimiento().getUltimaCaravana();

        }

    }//GEN-LAST:event_jRBnoItemStateChanged

    private void jBagregarLoteActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBagregarLoteActionPerformed
        if ( !jFTFCaravanaInicial.isEditValid() )
            JOptionPane.showMessageDialog( this,
                                           "Debe ingresar un caravana inicial.",
                                           "Datos insuficientes",
                                           JOptionPane.INFORMATION_MESSAGE );
        else if ( jFTFCantidadCompradas.getValue() == null )
            JOptionPane.showMessageDialog( this, "Debe ingresar una cantidad.",
                                           "Datos insuficientes",
                                           JOptionPane.INFORMATION_MESSAGE );
            
        else if ( comprobarCaravanaPropia(
                (String)jFTFCaravanaInicial.getValue() )) {
            //limpiamos el text field de caravana
            jFTFCaravanaInicial.setValue( null );
            jFTFCaravanaInicial.requestFocus();
            
        } else {
            //obtengo la caravana inicial
            String caravanaInicial = (String)jFTFCaravanaInicial.getValue();

            //obtengo la cantidad
            int cantidad = Math.abs(
                    ( (Long)jFTFCantidadCompradas.getValue() ).intValue() );

            //generamos y agregamos las nuevas caravanas
            List<String> caravanas = AbstractAnimal.generarCaravanas(
                    caravanaInicial, cantidad, true );
            
            for ( int i = 0; i <= caravanas.size() - 1; i++ )
                if ( !caravanasListModel.contains( caravanas.get( i )) )
                    caravanasListModel.addElement( caravanas.get( i ) );

            //limpiamos los text fields
            jFTFCaravanaInicial.setValue( null );
            jFTFCantidadCompradas.setValue( null );            
            
        }
        
    }//GEN-LAST:event_jBagregarLoteActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel JPInputCaravanas;
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler2;
    private javax.swing.Box.Filler filler3;
    private javax.swing.Box.Filler filler4;
    private javax.swing.Box.Filler filler5;
    private javax.swing.Box.Filler filler6;
    private javax.swing.Box.Filler filler7;
    private javax.swing.Box.Filler filler8;
    private javax.swing.JButton jBLimpiar;
    private javax.swing.JButton jBQuitar;
    private javax.swing.JButton jBagregarLote;
    private javax.swing.JButton jBguardar;
    private javax.swing.JFormattedTextField jFTFCantidadCompradas;
    private javax.swing.JFormattedTextField jFTFCantidadPropias;
    private javax.swing.JFormattedTextField jFTFCaravana;
    private javax.swing.JFormattedTextField jFTFCaravanaInicial;
    private javax.swing.JFormattedTextField jFTFDta;
    private javax.swing.JFormattedTextField jFTFNumeroFactura;
    private javax.swing.JFormattedTextField jFTFRenspa;
    private javax.swing.JLabel jLCantidadCompradas;
    private javax.swing.JLabel jLCantidadPropias;
    private javax.swing.JLabel jLCaravana;
    private javax.swing.JLabel jLCaravanaInicial;
    private javax.swing.JLabel jLDTA;
    private javax.swing.JLabel jLGuardarWaitIcon;
    private javax.swing.JLabel jLNumeroFactura;
    private javax.swing.JLabel jLRenspa;
    private javax.swing.JLabel jLTRI;
    private javax.swing.JLabel jLTipoFactura;
    private javax.swing.JLabel jLTituloIngresoLote;
    private javax.swing.JLabel jLTituloIngresoManual;
    private javax.swing.JList jLcaravanas;
    private javax.swing.JLabel jLfecha;
    private javax.swing.JPanel jPCaravanas;
    private javax.swing.JPanel jPCaravanasCompradas;
    private javax.swing.JPanel jPCaravanasPropias;
    private javax.swing.JPanel jPCentral;
    private javax.swing.JPanel jPDatos;
    private javax.swing.JRadioButton jRBno;
    private javax.swing.JRadioButton jRBsi;
    private javax.swing.JScrollPane jSPCaravanas;
    private javax.swing.JSeparator jSSeparatorInputCaravana;
    private javax.swing.JTextField jTFTipoFactura;
    private org.jdesktop.swingx.JXDatePicker jXDPFecha;
    // End of variables declaration//GEN-END:variables

    /**
     * Realiza las tareas de GUI previas/posteriores al agregado por lote. 
     * Esto implica deshabilitar/habilitar los controles y mostrar una animación
     * de espera.
     * @param inicio indica si se deben usar los triggers de inicio o de fin.
     */
    private void fireGuardarTriggers( boolean inicio ) {
        if ( inicio ) {
            //deshabilitamos los controles
            jBguardar.setEnabled( false );

            //colocamos el icono de espera
            jLGuardarWaitIcon.setEnabled( true );
            jLGuardarWaitIcon.setIcon( loadingIcon );

        } else {
            //rehabilitamos los controles
            jBguardar.setEnabled( true );

            //quitamos el icono de espera
            jLGuardarWaitIcon.setEnabled( false );

        }

    }//end método fireGuardarTriggers

    /**
     * Limpia todos los campos del formulario.
     */
    protected void limpiarPanel() {
        jXDPFecha.setDate( new Date() );
        jTFTipoFactura.setText( "" );
        jTFTipoFactura.setEnabled( true );
        jFTFNumeroFactura.setValue( null );
        jFTFNumeroFactura.setEnabled( true );
        jFTFCantidadPropias.setValue( null );
        jFTFCaravana.setValue( null );
        jFTFCaravanaInicial.setValue( null);
        jFTFCantidadCompradas.setValue(null);
        jFTFDta.setValue( null );
        jFTFDta.setEnabled( false );
        jFTFRenspa.setValue( null );
        jFTFRenspa.setEnabled( false );
        jRBno.setSelected( true );
        jRBsi.setSelected( false );
        caravanasListModel.removeAllElements();

        //cambiamos el establecimiento      
        Establecimiento establecimiento = frame.getEstablecimiento();

        //reseteamos la ultima caravana 
        if ( establecimiento != null )
            ultimaCaravana = establecimiento.getUltimaCaravana();

    }//end método limpiarPanel
    
    /**
     * Método para pedir la última caravana del establecimiento en caso de no
     * tenerlo seteado.
     * @return <li>true si se ingresa una caravana válida <li>false si se ingresa
     * una caravana inválida.
     */
    private boolean pedirUltimaCaravana() {
        boolean res = true;
        
        //generamos el text field especifico para el establecimiento
        try {
            ultimaCaravanaComponents[1] = new JFormattedTextField(
                    new DefaultFormatterFactory(
                    new javax.swing.text.MaskFormatter(
                    String.format( "%sU###",
                                   frame.getEstablecimiento().getCuig().
                                   replace( "A", "'A" ).
                                   replace( "H", "'H" ).
                                   replace( "L", "'L" ).
                                   replace( "U", "'U" ) ) ) ) );
        
        } catch ( Exception ex ) {
            //ignore
            
        }
        
        JOptionPane.showMessageDialog( frame,
                                       ultimaCaravanaComponents,
                                       "Caravanas",
                                       JOptionPane.INFORMATION_MESSAGE );

        try {
            JFormattedTextField textCaravana =
                                (JFormattedTextField)ultimaCaravanaComponents[1];

            textCaravana.commitEdit();
            ultimaCaravana = (String)textCaravana.getValue();

        } catch ( Exception ex ) {
            JOptionPane.showMessageDialog( frame,
                                           "La caravana ingresada no és"
                                           + " válida.",
                                           "Error",
                                           JOptionPane.ERROR_MESSAGE );

            res = false;

        }
        
        return res;

    }//end método pedirUltimaCaravana
    
    /**
     * Comprueba si una caravana ingresada manualmente corresponde a un número
     * de caravana propio del establecimiento seteado.
     * @param caravana caravana a comprobar
     * @return <li>true si la caravana corresponde al establecimiento. 
     * <li> false si la caravana no corresponde al establecimineto.
     */
    private boolean comprobarCaravanaPropia( String caravana ) {
        boolean res = caravana.substring( 0, 5 ).equals(
                frame.getEstablecimiento().getCuig() );

        if ( res )
            JOptionPane.showMessageDialog( this,
                                           "La caravana ingresada corresponde"
                                           + " al establecimiento actual.",
                                           "Datos incorrectos",
                                           JOptionPane.INFORMATION_MESSAGE );
        
        return res;
        
    }//end método comprobarCaravanaPropia
    
    /**
     * La clase {@code CompraPersistenceHandler} es un handler para los 
     * eventos producidos por el {@code PersistenceWorker} utilizado para 
     * guardar la compra.
     */
    class CompraPeristenceHandler implements PersistenceListener {

        /** Establecimiento al que corresponde la compra. */
        private Establecimiento establecimiento;
        /** Bandera que indica si ocurrió un error durante la persistencia. */
        private boolean error;

        /**
         * Inicializa el handler para la compra sobre el establecimiento 
         * indicado.
         * @param establecimiento establecimiento en el que se realizó la 
         * compra.
         */
        public CompraPeristenceHandler( Establecimiento establecimiento ) {
            this.establecimiento = establecimiento;

        }//end constructor

        /**
         * {@inheritDoc}
         */
        @Override
        public void donePersisting() {
            //si hay errores, reactivamos la interfaz y salimos.
            if ( error ) {
                fireGuardarTriggers( false );
                
                return;
                
            }//end if

            //seteamos la nueva última caravana al establecimiento
            establecimiento.setUltimaCaravana( ultimaCaravana );

            //creamos un nuevo worker para persistir los datos del estab
            PersistenceWorker worker = new PersistenceWorker( establecimiento );

            worker.addPersistenceListener(
                    new EstablecimientoPersistenceHandler() );
            
            worker.execute();

        }//end método donePersisting

        /**
         * {@inheritDoc}
         */
        @Override
        public void errorPersisting( ExecutionException ex ) {
            error = true;
           
            //corroboramos el tipo de error
            if ( ex.getCause() instanceof AnimalDuplicadoException ) {                                                           
                List<String> caravanas= ((AnimalDuplicadoException)
                        ex.getCause()).getCarvanasDuplicadas();

                int indices[] = new int[caravanas.size()];
                
                for ( int i = 0; i < indices.length; i++ )
                    indices[i] = caravanasListModel.indexOf( caravanas.get( i ) );
                                                
                JOptionPane.showMessageDialog( frame,
                                               "Se encontraron caravanas "
                                               + "duplicadas en la lista de "
                                               + "caravanas.",
                                               "Error",
                                               JOptionPane.ERROR_MESSAGE );
                
                jLcaravanas.setSelectedIndices( indices );
                
            } else {                
                frame.recoverFromFail();
                
            }
            
        }//end método errorPersisting

    }//end clase CompraPersistenceHandler

    /**
     * La clase {@code EstablecimientoPersitenceHandler} implementa un listener
     * para recibir eventos de un {@code PersistenceWorker} utilizado para
     * persistir cambios en el establecimiento.
     */
    class EstablecimientoPersistenceHandler implements PersistenceListener {
        /** Bandera que indica si ocurrió un error durante la persistencia. */
        private boolean error;

        /**
         * {@inheritDoc}
         */
        @Override
        public void donePersisting() {
            fireGuardarTriggers( false );

            //si ocurrió un error, no borramos los datos ni mostramos mensaje
            if ( !error ) {
                //limpiamos el formulario
                limpiarPanel();

                //informamos que se guardo con éxito
                JOptionPane.showMessageDialog(
                        ComprasPanel.this, "Compra guardada.",
                        "Completado", JOptionPane.INFORMATION_MESSAGE );

            }//end if

        }//end método donePersisting

        /**
         * {@inheritDoc}
         */
        @Override
        public void errorPersisting( ExecutionException ex ) {
            error = true;

            frame.recoverFromFail();
            
        }//end método errorPersisting

    }//end clsae EstablecimientoPersitenceHandler
    
    /**
     * Método que verifica la existencia de la compra en la bd
     * @param compra compra a verificar
     * @return verdadero si la compra no existe, falso de otro modo
     */
    private boolean validarDatos(Compra compra){
        boolean validado = false;
        BusquedaCompra busqueda = new BusquedaCompra();
        BusquedaCompraHistorica busquedaHistorica = new BusquedaCompraHistorica();
        
        //si la compra es con tri...
        if( rBGroup.isSelected( jRBsi.getModel() ) ){
            busqueda.porDta( compra.getDtaOrigen() );
            busqueda.porRenspa( compra.getRenspaOrigen() );
            busquedaHistorica.porDta( compra.getDtaOrigen() );
            busquedaHistorica.porRenspa( compra.getRenspaOrigen() );
            
        }
        else{
            busqueda.porNumeroDeFactura( compra.getNroFactura() );
            busqueda.porTipoFactura( compra.getTipoFactura() );
            busquedaHistorica.porNumeroDeFactura( compra.getNroFactura() );
            busquedaHistorica.porTipoFactura( compra.getTipoFactura() );
            
        }
        
        if(busqueda.resultadoUnico() == null && 
           busquedaHistorica.resultadoUnico() == null)
                validado = true;
        
        return validado;
        
    }//end metodo validarDatos

}//end clase ComprasPanel
